﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace cs2335lab3grp1
{
    /// <summary>
    /// StudentList holds a class name and a list of Student objects.
    /// It can output a human-readable string of its information
    /// Has methods to add, remove, and check if it contains a particular Student
    /// And can find the average and standard deviation of this class.
    /// </summary>
    [XmlRoot("Gradebook")]
    public class StudentList
    {
        #region constructors
        public StudentList()
            : this("no classname", new List<Student>())
        {
            // default constructor
        }
        public StudentList(string classname)
            : this(classname, new List<Student>())
        {
            // use two-var constructor
        }
        public StudentList(string classname, List<Student> students)
        {
            this.classname = classname;
            this.students = students;
        }
        #endregion
        #region instance variables and properties
        private List<Student> students;
        public List<Student> Students
        {
            get { return students; }
            set { students = value; }
        }
        private string classname;
        public string Classname
        {
            get { return classname; }
            set { classname = value; }
        }
        #endregion
        #region methods
        /// <summary>
        /// Converts this StudentList's info to a human-readable string.
        /// </summary>
        /// <returns>Info string for this StudentList.</returns>
        public override string ToString()
        {
            // output variable
            string output = "GradeBook Report for ";
            output += classname;
            output += "\n";

            // list each student's name and grade
            foreach(Student s in students)
            {
                output += s.ToString();
                output += "\n";
            }

            // list the class avg and deviation
            output += "\nClass Average = ";
            output += Average();
            output += "\nClass Deviation = ";
            output += StandardDeviation();

            // return the string
            return output;
        }
        
        /// <summary>
        /// Returns the class average for this StudentList.
        /// </summary>
        /// <returns>A double with this class' average.</returns>
        public double Average()
        {
            // loop through students, 
            // find each student's average and sum them
            double sum = 0;
            foreach (Student s in students)
            {
                sum += s.Average();
            }

            // divide by the number of students 
            // and round to two decimal places
            double avg = Math.Round(sum / students.Count, 2);
            return avg;
        }
        
        /// <summary>
        /// Returns the std. deviation for this class.
        /// </summary>
        /// <returns>A double with this class' std. deviation.</returns>
        public double StandardDeviation()
        {
            // find the average
            double avg = Average();

            // find the sum squared
            double sum = 0;
            foreach (Student s in students)
            {
                double savg = s.Average();
                sum += savg * savg;
            }

            // find the sum squared average
            double sumavg = sum / students.Count;

            // find the standard deviation and round
            double stddev = Math.Round(Math.Sqrt(sumavg - avg * avg), 2);
            return stddev;
        }
        
        /// <summary>
        /// Adds a student to this StudentList.
        /// </summary>
        /// <param name="s">Student to add.</param>
        public void AddStudent(Student s)
        {
            // add a student to the list
            students.Add(s);
        }

        /// <summary>
        /// Removes a student from this StudentList.
        /// </summary>
        /// <param name="s">Student to remove.</param>
        /// <returns>A boolean indicating successful removal.</returns>
        public bool RemoveStudent(Student s)
        {
            // remove a student from the list
            return students.Remove(s);
        }

        /// <summary>
        /// Returns whether the specified Student is in this
        /// StudentList.
        /// </summary>
        /// <param name="s">Student being inquired.</param>
        /// <returns>Boolean indicating whether the Student
        /// exists in this StudentList.</returns>
        public bool Contains(Student s)
        {
            // check if a student is in the list
            return students.Contains(s);
        }
        #endregion
    }
}
